package g

import "math"

/*
 * @lc app=leetcode.cn id=8 lang=golang
 *
 * [8] 字符串转换整数 (atoi)
请你来实现一个 myAtoi(string s) 函数，使其能将字符串转换成一个 32 位有符号整数（类似 C/C++ 中的 atoi 函数）。

函数 myAtoi(string s) 的算法如下：

1. 读入字符串并丢弃无用的前导空格
2. 检查下一个字符（假设还未到字符末尾）为正还是负号，读取该字符（如果有）。
确定最终结果是负数还是正数。 如果两者都不存在，则假定结果为正。
3. 读入下一个字符，直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
4. 将前面步骤读入的这些数字转换为整数（即，"123" -> 123， "0032" -> 32）。
如果没有读入数字，则整数为 0 。必要时更改符号（从步骤 2 开始）。
5. 如果整数数超过 32 位有符号整数范围 [−2^31,  2^31 − 1] ，需要截断这个整数，使其保持在这个范围内。
具体来说，小于 −2^31 的整数应该被固定为 −2^31 ，大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
返回整数作为最终结果。
注意：

本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外，请勿忽略任何其他字符。

0 <= s.length <= 200
s 由英文字母（大写和小写）、数字（0-9）、' '、'+'、'-' 和 '.' 组成
*/

// @lc code=start
func myAtoi(s string) int {
	return myAtoiSlice(s)
	// return myAtoiSrc(s)
}

func myAtoiSrc(s string) int {
	// 去除前边的空格
	var begIndex int
	for i := begIndex; i < len(s); i++ {
		if s[i] == ' ' {
			begIndex++
		} else {
			break
		}
	}
	if begIndex == len(s) {
		return 0
	}
	// 获取符号
	sign := 1
	if s[begIndex] == '-' {
		sign = -1
		begIndex++
	} else if s[begIndex] == '+' {
		begIndex++
	}
	if begIndex == len(s) {
		return 0
	}
	// 获取有效数字前后索引，最后begIndex可能指向的还是无效数字(当endIndex==-1的时候)
	flagFind := false // 表示是否找到第一个非0位数
	endIndex := -1    // 此时beg可能指向无效数字
	for i := begIndex; i < len(s); i++ {
		if flagFind == false { //去除前边的无效0位
			begIndex = i
			if s[i] == '0' {
				continue
			}
			flagFind = true
		}
		if s[i] >= '0' && s[i] <= '9' {
			endIndex = i
		} else {
			break
		}
		// 位数越界，直接返回最大值或最小值
		if (endIndex - begIndex + 1) == 11 { // math.MaxInt32=2147483647
			if sign == -1 {
				return math.MinInt32
			}
			return math.MaxInt32
		}
	}
	// 计算值,nums 最多10位
	var val int64
	bitSize := int(math.Pow(10, float64(endIndex-begIndex))) //最大1000000000
	for i := begIndex; i <= endIndex; i++ {
		val += int64(int(s[i]-'0') * bitSize)
		bitSize /= 10
	}
	val = int64(sign) * val
	// 排查越界情况
	if val > math.MaxInt32 {
		val = math.MaxInt32
	} else if val < math.MinInt32 {
		val = math.MinInt32
	}
	return int(val)
}

func myAtoiSlice(s string) int {
	// 去除前边的空格和0
	var beg int
	for i := beg; i < len(s); i++ {
		if s[i] == ' ' {
			beg++
		} else {
			break
		}
	}
	if beg == len(s) {
		return 0
	}
	// 获取符号
	sign := 1
	if s[beg] == '-' {
		sign = -1
		beg++
	} else if s[beg] == '+' {
		beg++
	}
	// 获取有效数字
	var nums []byte
	for i := beg; i < len(s); i++ {
		if s[i] >= '0' && s[i] <= '9' {
			nums = append(nums, s[i])
		} else {
			break
		}
		if nums[0] == '0' { //去除前边的无效0位
			nums = nums[1:]
		}
		if len(nums) == 11 { // math.MaxInt32=2147483647
			if sign == -1 {
				return math.MinInt32
			}
			return math.MaxInt32
		}
	}
	// 计算值,nums最多10位
	var val int64
	bitSize := int(math.Pow(10, float64(len(nums)-1))) //最大1000000000
	for i := 0; i < len(nums); i++ {
		val += int64(int(nums[i]-'0') * bitSize)
		bitSize /= 10
	}
	val = int64(sign) * val
	// 排查越界情况
	if val > math.MaxInt32 {
		val = math.MaxInt32
	} else if val < math.MinInt32 {
		val = math.MinInt32
	}
	return int(val)
}

// @lc code=end
